home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / KeyboardModule / KeyboardModule.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  19.0 KB  |  496 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        KeyboardModule.c
  3.  
  4.     Contains:    HID Module for USB Keyboard
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1999 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Devices.h>
  13. #include <DriverServices.h>
  14. #include <Gestalt.h>
  15. #include <MacTypes.h>
  16. #include <Processes.h>
  17. #include <USB.h>
  18.  
  19. #include "KeyboardModule.h"
  20. #include "PackageVersion.h"
  21.  
  22. usbKeyboardPBStruct myKeyboardPB;
  23. usbKeyboardPBStruct shimKeyboardPB;
  24.  
  25.  
  26.  
  27. void InitParamBlock(USBReference theInterfaceRef, USBPB * paramblock)
  28. {
  29.     paramblock->usbReference = theInterfaceRef;
  30.     paramblock->pbVersion = kUSBCurrentPBVersion;
  31.     
  32.     paramblock->usb.cntl.WIndex = 0;             
  33.     paramblock->usb.cntl.WValue = 0;
  34.     
  35.     paramblock->usbBuffer = nil;        
  36.     paramblock->usbActCount = 0;
  37.     paramblock->usbReqCount = 0;
  38.     paramblock->usbFlags = 0;
  39.     paramblock->usbOther = 0;
  40.     
  41.     paramblock->usbStatus = noErr;
  42. }
  43.  
  44. static Boolean immediateError(OSStatus err)
  45. {
  46.     return((err != kUSBPending) && (err != noErr) );
  47. }
  48.  
  49. void KeyboardInitiateTransaction(USBPB *pb)
  50. {
  51. register usbKeyboardPBStruct *pKeyboardPB;
  52. OSStatus myErr;
  53.  
  54.     pKeyboardPB = (usbKeyboardPBStruct *)(pb);
  55.  
  56. //USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": KeyboardInitiateTransaction PB", (long)pKeyboardPB);
  57. //USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": KeyboardInitiateTransaction ref", (long)pKeyboardPB->pb.usbRefcon);
  58.  
  59.     pKeyboardPB->transDepth++;
  60.     if (pKeyboardPB->transDepth < 0)
  61.     {
  62.         USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": transDepth < 0 (initiation)", pKeyboardPB->transDepth);
  63.         //USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": transDepth < 0 (initiation)", pKeyboardPB->pb.usbRefcon );
  64.     }
  65.     
  66.     if (pKeyboardPB->transDepth > 1)
  67.     {
  68.         USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": transDepth >1 (initiation)", pKeyboardPB->transDepth);
  69.         return;    // trying to reuse PB, bail out before we cause more problems.
  70.         //USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": transDepth > 1 (initiation)", pKeyboardPB->pb.usbRefcon );
  71.     }
  72.     
  73.     if (pKeyboardPB->driverRemovalPending)
  74.     {
  75.         pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  76.         return;
  77.     }
  78.     
  79.     switch(pKeyboardPB->pb.usbRefcon & ~kRetryTransaction)
  80.     {
  81.         case kSetKeyboardLEDs:
  82.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  83.             
  84.             pKeyboardPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  85.             
  86.             pKeyboardPB->pb.usb.cntl.BRequest = kHIDRqSetReport;
  87.             pKeyboardPB->pb.usb.cntl.WValue = (kHIDRtOutputReport << 8); 
  88.             pKeyboardPB->pb.usb.cntl.WIndex = pKeyboardPB->interfaceDescriptor.interfaceNumber;
  89.             
  90.             pKeyboardPB->pb.usbBuffer = (Ptr)&pKeyboardPB->hidReport[0];
  91.             pKeyboardPB->pb.usbReqCount = 1;
  92.                 
  93.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  94.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  95.             
  96.             myErr = USBDeviceRequest(&pKeyboardPB->pb);
  97.             if(immediateError(myErr))
  98.             {
  99.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kSetKeyboardLEDs - immediate error", myErr);
  100.             }
  101.             break;
  102.  
  103.         case kConfigureInterface:
  104.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  105.             
  106.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  107.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  108.             
  109.             myErr = USBConfigureInterface( &pKeyboardPB->pb );
  110.             if(immediateError(myErr))
  111.             {
  112.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kConfigureInterface - immediate error", myErr);
  113.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  114.             }
  115.             break;
  116.         
  117.         case kSetProtocol:
  118.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  119.             
  120.             pKeyboardPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  121.             pKeyboardPB->pb.usb.cntl.BRequest = kHIDRqSetProtocol;
  122.             pKeyboardPB->pb.usb.cntl.WValue = kHIDBootProtocolValue; 
  123.             pKeyboardPB->pb.usb.cntl.WIndex = pKeyboardPB->interfaceDescriptor.interfaceNumber;
  124.             
  125.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  126.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  127.         
  128.             myErr = USBDeviceRequest(&pKeyboardPB->pb);
  129.             if (immediateError(myErr))
  130.             {
  131.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kSetProtocol - immediate error", myErr);
  132.             }
  133.             break;
  134.             
  135.         case kSetIdleRequest:
  136.             USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": Do a SetIdle on non-Apple keyboards, as some 3rd party keyboards don't send reports on key release", pKeyboardPB->pipeRef);
  137.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  138.             
  139.             pKeyboardPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);            
  140.             
  141.             pKeyboardPB->pb.usb.cntl.BRequest = kHIDRqSetIdle;
  142.             pKeyboardPB->pb.usb.cntl.WValue = ((24/4)<<8);                 // force a read completion if idle for more than 24ms
  143.             pKeyboardPB->pb.usb.cntl.WIndex = pKeyboardPB->interfaceDescriptor.interfaceNumber;
  144.             
  145.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  146.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  147.  
  148.             myErr = USBDeviceRequest(&pKeyboardPB->pb);
  149.             if(immediateError(myErr))
  150.             {
  151.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kSetIdleRequest - immediate error", myErr);
  152.             }
  153.             break;
  154.  
  155.         case kFindPipe:
  156.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  157.             
  158.             pKeyboardPB->pb.usbFlags = kUSBIn;
  159.             pKeyboardPB->pb.usbClassType = kUSBInterrupt;
  160.             
  161.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  162.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  163.  
  164.             myErr = USBFindNextPipe( &pKeyboardPB->pb );
  165.             if((immediateError(myErr)) || (pKeyboardPB->pb.usbBuffer == nil))
  166.             {
  167.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kFindPipe - immediate error", myErr);
  168.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  169.             }
  170.             break;
  171.  
  172.         case kReadInterruptPipe:
  173.             InitParamBlock(pKeyboardPB->pipeRef, &pKeyboardPB->pb);
  174.  
  175.             pKeyboardPB->pb.usbBuffer = (Ptr)pKeyboardPB->hidReport;
  176.             pKeyboardPB->pb.usbReqCount = 0x08;
  177.             pKeyboardPB->pb.usb.cntl.WIndex = pKeyboardPB->interfaceDescriptor.interfaceNumber;    
  178.             
  179.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  180.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  181.                         
  182.             //    Get USB Version to to see if we support the debug aware flag ( version > 1.4 )
  183.             if ( pKeyboardPB->usbVersion >=  kUSBVersion14 )
  184.             {
  185.                 pKeyboardPB->pb.usbFlags |= kUSBDebugAwareFlag;
  186.             }
  187.             
  188.             myErr = USBIntRead(&pKeyboardPB->pb);
  189.             if(immediateError(myErr))
  190.             {
  191.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kReadInterruptPipe - immediate error", myErr);
  192.             }
  193.             break;
  194.  
  195.         case kClearFeature:
  196.             USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": Do a clear feature on the interrupt endpoint", pKeyboardPB->pipeRef);
  197.             InitParamBlock(pKeyboardPB->pipeRef, &pKeyboardPB->pb);
  198.             pKeyboardPB->pb.usb.cntl.BMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBEndpoint);
  199.             
  200.             pKeyboardPB->pb.usb.cntl.BRequest = kUSBRqClearFeature;
  201.             pKeyboardPB->pb.usb.cntl.WValue = kUSBFeatureEndpointStall;
  202.             
  203.             pKeyboardPB->pb.usbFlags = kUSBAddressRequest;                /* kUSBAddressRequest asks the USL to do a translation of piperef to endpoint number */
  204.  
  205.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  206.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  207.  
  208.             myErr = USBDeviceRequest(pb);
  209.             if(immediateError(myErr))
  210.             {
  211.                 USBExpertFatalError(pKeyboardPB->pb.usbReference, kUSBInternalErr, kKeyboardModuleName": kClearFeature - immediate error", myErr);
  212.             }
  213.             break;
  214.                 
  215.         case kResetMouse:
  216.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  217.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  218.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  219.             myErr = USBResetDevice( &pKeyboardPB->pb );
  220.             if(myErr == kUSBDeviceBusy)
  221.             {
  222.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": reset busy, backing off", myErr);
  223.                 pKeyboardPB->pb.usbReqCount = 100;
  224.                 pKeyboardPB->pb.usbRefcon = kResetMouseDelay | kCompletionPending;
  225.                 pKeyboardPB->pb.usbFlags = kUSBReturnOnException;
  226.                 USBDelay(  &pKeyboardPB->pb );
  227.             }
  228.             else if(immediateError(myErr))
  229.             {
  230.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kResetMouse - immediate error", myErr);
  231.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  232.             }
  233.             break;
  234.  
  235.         case kGetPortStatus:
  236.             InitParamBlock(pKeyboardPB->interfaceRef, &pKeyboardPB->pb);
  237.             pKeyboardPB->pb.usbCompletion = (USBCompletion)KeyboardCompletionProc;
  238.             pKeyboardPB->pb.usbRefcon |= kCompletionPending;
  239.             myErr = USBPortStatus(  &pKeyboardPB->pb );
  240.             if(myErr == kUSBDeviceBusy)
  241.             {
  242.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": status busy, backing off", myErr);
  243.                 pKeyboardPB->pb.usbReqCount = 100;
  244.                 pKeyboardPB->pb.usbRefcon = kPortStatusDelay | kCompletionPending;
  245.                 pKeyboardPB->pb.usbFlags = kUSBReturnOnException;
  246.                 USBDelay(  &pKeyboardPB->pb );
  247.             }
  248.             else if(immediateError(myErr))
  249.             {
  250.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": kGetPortStatus - immediate error", myErr);
  251.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  252.             }
  253.             break;
  254.  
  255.         default:
  256.             USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName" - Transaction completed with bad refcon value", pKeyboardPB->pb.usbRefcon );
  257.             pKeyboardPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  258.             break;
  259.     }
  260.     
  261. // At this point the control is returned to the system.  If a USB transaction
  262. // has been initiated, then it will call the Completion proc
  263. // (below) to handle the results of the transaction.
  264. }
  265.  
  266. void KeyboardCompletionProc(USBPB *pb)
  267. {
  268. unsigned char    * errstring;
  269. register usbKeyboardPBStruct *pKeyboardPB;
  270. USBPipeState pipeState;
  271.  
  272.  
  273.     pKeyboardPB = (usbKeyboardPBStruct *)(pb);
  274. //USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": KeyboardCompletionProc PB", (long)pKeyboardPB);
  275. //USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": KeyboardCompletionProc ref", (long)pKeyboardPB->pb.usbRefcon);
  276.     pKeyboardPB->transDepth--;
  277.     if (pKeyboardPB->transDepth < 0)
  278.     {
  279.         //USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": transDepth < 0 (completion)", pKeyboardPB->pb.usbRefcon );
  280.         USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": transDepth <0 (completion) exiting", pKeyboardPB->transDepth);
  281.         return;    // pb being reused, bail before we cause more damage
  282.     }
  283.     
  284.     if (pKeyboardPB->transDepth > 1)
  285.     {
  286.         USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": transDepth >1 (completion)", pKeyboardPB->transDepth);
  287.         //USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName": transDepth > 1 (completion)", pKeyboardPB->pb.usbRefcon );
  288.     }
  289.     
  290.     if( (pKeyboardPB->pb.usbStatus != noErr) && ((pKeyboardPB->pb.usbRefcon & kStageMask) != kGetPortStatus) )        // was there an error?
  291.     {
  292.         switch(pKeyboardPB->pb.usbRefcon & 0x0fff)                                            // yes, so show where the error occurred
  293.         {
  294.             case kSetKeyboardLEDs:              errstring = kKeyboardModuleName": Error during kSetKeyboardLEDs"; break;
  295.             case kConfigureInterface:            errstring = kKeyboardModuleName": Error during kConfigureInterface"; break;
  296.             case kSetProtocol:                    errstring = kKeyboardModuleName": Error during kSetProtocol"; break;
  297.             case kSetIdleRequest:                  errstring = kKeyboardModuleName": Error during kSetIdleRequest"; break;
  298.             case kFindPipe:                      errstring = kKeyboardModuleName": Error during kFindPipe"; break;
  299.             case kReadInterruptPipe:              errstring = kKeyboardModuleName": Error during kReadInterruptPipe"; break;
  300.             case kClearFeature:                  errstring = kKeyboardModuleName": Error during kClearFeature"; break;
  301.             default:                              errstring = kKeyboardModuleName": Error occurred, but state is unknown"; break;
  302.         };
  303.         USBExpertFatalError(pKeyboardPB->interfaceRef, pKeyboardPB->pb.usbStatus, errstring, (pKeyboardPB->pb.usbRefcon & 0x0fff));
  304.         
  305.         pKeyboardPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);                // set up to retry the transaction
  306.         pKeyboardPB->pb.usbRefcon |= kRetryTransaction;
  307.         pKeyboardPB->retryCount--;
  308.         
  309.         if ((!pKeyboardPB->retryCount)    || (pKeyboardPB->pb.usbStatus == kUSBAbortedError))    // have we exhausted the retries?
  310.         {                                                                                    // or received an abort?
  311.             USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": Pipe abort or unable to recover from error", pKeyboardPB->interfaceRef);
  312.             pKeyboardPB->pb.usbRefcon = kReturnFromDriver;                                    // if so, just exit.
  313.             pKeyboardPB->intPipeAborted = true;                                                
  314.         }
  315.         else                                                                                // if it didn't abort and there's retries left, then...
  316.         {
  317.             if (pKeyboardPB->pipeRef)                                                        // check if the pipe is open.
  318.             {
  319.                 USBGetPipeStatusByReference(pKeyboardPB->pipeRef, &pipeState);                // yes, so what it's state?
  320.                 if (pipeState != kUSBActive)                                                // if it's not active, try to clear it.  It might be stalled...
  321.                 {
  322.                     USBExpertStatus(pKeyboardPB->interfaceRef, kKeyboardModuleName": Pipe is open and stalled, clearing stall...", pKeyboardPB->interfaceRef);
  323.                     USBClearPipeStallByReference(pKeyboardPB->pipeRef);
  324.                 }
  325.             }
  326.             if( (pKeyboardPB->pb.usbStatus == kUSBNotRespondingErr)  ) 
  327.             {
  328.                 USBExpertStatusLevel(1, pKeyboardPB->interfaceRef, kKeyboardModuleName": doing port status", pKeyboardPB->interfaceRef);
  329.                 pKeyboardPB->previousState = pKeyboardPB->pb.usbRefcon;
  330.                 pKeyboardPB->pb.usbRefcon = kGetPortStatus;
  331.             
  332.             }
  333.         }
  334.     }
  335.     else
  336.     {
  337.         pKeyboardPB->pb.usbRefcon &= ~kRetryTransaction;
  338.         pKeyboardPB->retryCount = kKeyboardRetryCount;
  339.     }
  340.  
  341.     if (pKeyboardPB->pb.usbRefcon & kCompletionPending)             
  342.     {                                                
  343.         pKeyboardPB->pb.usbRefcon &= ~(kCompletionPending + kReturnFromDriver);
  344.         switch(pKeyboardPB->pb.usbRefcon)
  345.         {
  346.             case kSetKeyboardLEDs:
  347.                 pKeyboardPB->pb.usbRefcon = kReturnFromDriver;
  348.                 pKeyboardPB->keyboardReady = true;
  349.                 break;
  350.                 
  351.             case kConfigureInterface:
  352.                 pKeyboardPB->pb.usbRefcon = kSetProtocol;
  353.                 break;
  354.                 
  355.             case kSetProtocol:
  356.                 if (kVendorID_AppleComputer == USBToHostWord(pKeyboardPB->deviceDescriptor.vendor))
  357.                 {
  358.                     pKeyboardPB->pb.usbRefcon = kFindPipe;
  359.                 }
  360.                 else
  361.                 {
  362.                     pKeyboardPB->pb.usbRefcon = kSetIdleRequest;
  363.                 }
  364.                 break;
  365.                 
  366.             case kSetIdleRequest:
  367.                 pKeyboardPB->pb.usbRefcon = kFindPipe;
  368.                 break;
  369.  
  370.             case kFindPipe:
  371.                 pKeyboardPB->pipeRef = pKeyboardPB->pb.usbReference;
  372.                 pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
  373.                 pKeyboardPB->keyboardReady = true;
  374.                 shimKeyboardPB.keyboardReady = true;
  375.                 break;
  376.                 
  377.             case kReadInterruptPipe:
  378.                 NotifyRegisteredHIDUser(pKeyboardPB->hidDeviceType, pKeyboardPB->hidReport);
  379.                 pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
  380.                 break;
  381.                 
  382.             case kClearFeature:
  383.                 pKeyboardPB->pb.usbRefcon = kReadInterruptPipe;
  384.                 break;
  385.                 
  386.             case kPortStatusDelay:
  387.                     USBExpertStatusLevel(1, pKeyboardPB->interfaceRef, kKeyboardModuleName": kPortStatusDelay", pKeyboardPB->interfaceRef);
  388.                     pKeyboardPB->pb.usbRefcon = kGetPortStatus;
  389.                 break;
  390.  
  391.             case kResetMouseDelay:
  392.                     USBExpertStatusLevel(1, pKeyboardPB->interfaceRef, kKeyboardModuleName": kPortStatusDelay", pKeyboardPB->interfaceRef);
  393.                     pKeyboardPB->pb.usbRefcon = kResetMouse;
  394.                 break;
  395.  
  396.             case kResetMouse:
  397.                     USBExpertStatusLevel(1, pKeyboardPB->interfaceRef, kKeyboardModuleName": mouse now reset", pKeyboardPB->interfaceRef);
  398.                     // Just give up here, the composite driver should now take care of things.
  399.                 break;
  400.  
  401.             case kGetPortStatus:
  402.                 if(pb->usbStatus == kUSBDeviceDisconnected)
  403.                 {
  404.                     USBExpertStatusLevel(1, pKeyboardPB->interfaceRef, kKeyboardModuleName": port status gives device disconnected, exiting", pKeyboardPB->interfaceRef);
  405.                     pKeyboardPB->pb.usbRefcon = kReturnFromDriver;            // if so, just exit.
  406.                 }
  407.                 else if(pb->usbStatus == kUSBPortDisabled)
  408.                 {
  409.                     USBExpertStatusLevel(1, pKeyboardPB->interfaceRef, kKeyboardModuleName": port status gives port disabled, resetting", pKeyboardPB->interfaceRef);
  410.                     pKeyboardPB->pb.usbRefcon = kResetMouse;
  411.                 }
  412.                 else if(pb->usbStatus == noErr)
  413.                 {
  414.                     USBExpertStatusLevel(1, pKeyboardPB->interfaceRef, kKeyboardModuleName": port status transient error, restarting", pKeyboardPB->interfaceRef);
  415.                     //pKeyboardPB->retryCount = kMouseRetryCount;    --> done automatically
  416.  
  417.                     pKeyboardPB->pb.usbRefcon = pKeyboardPB->previousState;
  418.                 }
  419.                 else
  420.                 {
  421.                     USBExpertStatusLevel(1, pKeyboardPB->interfaceRef, kKeyboardModuleName": port status unknown error", pb->usbStatus);
  422.                 }
  423.             
  424.                 break;
  425.  
  426.             default:
  427.                 USBExpertFatalError(pKeyboardPB->interfaceRef, kUSBInternalErr, kKeyboardModuleName" - Transaction completed with bad refcon value", pKeyboardPB->pb.usbRefcon );
  428.                 pKeyboardPB->pb.usbRefcon = kUndefined + kReturnFromDriver;
  429.                 break;
  430.         }
  431.     }
  432.     if (!(pKeyboardPB->pb.usbRefcon & kReturnFromDriver) && (!pKeyboardPB->driverRemovalPending))
  433.         KeyboardInitiateTransaction(pb);
  434. }
  435.  
  436.  
  437. void InterfaceEntry(UInt32 interfacenum, USBInterfaceDescriptorPtr pInterfaceDescriptor, USBDeviceDescriptorPtr pDeviceDescriptor, USBReference theInterfaceRef)
  438. {
  439. #pragma unused (interfacenum)
  440.  
  441. static Boolean beenThereDoneThat = false;
  442.  
  443.     if(beenThereDoneThat)
  444.     {
  445.         USBExpertFatalError(theInterfaceRef, kUSBInternalErr, kKeyboardModuleName" is not reentrant", 12);
  446.         return;
  447.     }
  448.     beenThereDoneThat = true;
  449.     
  450.     //DebugStr("\pIn Keyboard Module Interface entry routine");
  451.     shimKeyboardPB.driverRemovalPending = false;
  452.     shimKeyboardPB.deviceDescriptor = *pDeviceDescriptor;                
  453.     shimKeyboardPB.interfaceDescriptor = *pInterfaceDescriptor;                
  454.     shimKeyboardPB.transDepth = 0;                            
  455.     shimKeyboardPB.retryCount = kKeyboardRetryCount;
  456.     shimKeyboardPB.pSHIMInterruptRoutine = nil;
  457.     shimKeyboardPB.pSavedInterruptRoutine = nil;
  458.     shimKeyboardPB.interfaceRef = theInterfaceRef;
  459.     shimKeyboardPB.pipeRef = 0;
  460.     shimKeyboardPB.keyboardReady = false;
  461.     shimKeyboardPB.intPipeAborted = false;
  462.     
  463.     InitParamBlock(theInterfaceRef, &shimKeyboardPB.pb);
  464.     shimKeyboardPB.pb.pbLength = sizeof(usbKeyboardPBStruct);
  465.     shimKeyboardPB.pb.usbRefcon = 0;                
  466.  
  467.     myKeyboardPB.driverRemovalPending = false;
  468.     myKeyboardPB.deviceDescriptor = *pDeviceDescriptor;                
  469.     myKeyboardPB.interfaceDescriptor = *pInterfaceDescriptor;                
  470.     myKeyboardPB.transDepth = 0;                            
  471.     myKeyboardPB.retryCount = kKeyboardRetryCount;
  472.     myKeyboardPB.pSHIMInterruptRoutine = nil;
  473.     myKeyboardPB.pSavedInterruptRoutine = nil;
  474.     myKeyboardPB.interfaceRef = theInterfaceRef;
  475.     myKeyboardPB.pipeRef = 0;
  476.     myKeyboardPB.keyboardReady = false;
  477.     myKeyboardPB.intPipeAborted = false;
  478.  
  479.     myKeyboardPB.sendRawReportFlag = false;
  480.     myKeyboardPB.hidEmulationInit = false;
  481.     
  482.     InitParamBlock(theInterfaceRef, &myKeyboardPB.pb);
  483.     myKeyboardPB.pb.pbLength = sizeof(usbKeyboardPBStruct);
  484.     myKeyboardPB.pb.usbRefcon = kConfigureInterface;                    
  485.     
  486.     myKeyboardPB.usbVersion = 0;
  487.     (void) Gestalt(gestaltUSBVersion,&myKeyboardPB.usbVersion);
  488.  
  489.     USBHIDControlDevice(kHIDEnableDemoMode,0);
  490.     USBExpertStatusLevel(4, myKeyboardPB.interfaceRef, kKeyboardModuleName": starting up", 0);
  491.     KeyboardInitiateTransaction(&myKeyboardPB.pb);
  492. }
  493.  
  494.  
  495.  
  496.